package com.hyl.reflection;

import com.hyl.entity.Student;
import org.junit.Test;

import java.lang.reflect.*;

/**
 * StudentReflection
 *
 * @author hyl
 * @date 2025-06-06
 */
public class StudentReflection {

    @Test
    public void testClassInfo(){
        //1.获取Class类的实例
//        Student student = new Student();
//        Class clazz1 = student.getClass(); //方式1:了解
        Class clazz2 = Student.class; //方式2：常规
        Class clazz3 = null;
        try {
            clazz3 = Class.forName("com.hyl.entity.Student"); //方式3：推荐
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        System.out.println("类的基本信息");
        System.out.println("包名:" + clazz3.getPackage());
        System.out.println("类名:" + clazz3.getName());
        System.out.println("类的全路径:" + clazz3.getCanonicalName());
        System.out.println("类的父类:" + clazz3.getSuperclass());
        System.out.println("类的实现的接口:"+clazz3.getInterfaces());
        System.out.println("类的修饰符:"+clazz3.getModifiers());
        int modifiers = clazz3.getModifiers();
        if(Modifier.isPublic(modifiers)){
            System.out.println("类是public的");
        }else if(Modifier.isPrivate(modifiers)){
            System.out.println("private");
        }
    }

    @Test
    public void testClassConstructor() throws ClassNotFoundException {
        System.out.println("---------获取类的构造器-------");
        //1.获取Class类的实例
        Class clz = Class.forName("com.hyl.entity.Student");
        //2.获取类的构造器
        Constructor[] constructors = clz.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            int modifiers = constructor.getModifiers();
            System.out.print("访问修饰符："+getModifiersMsg(modifiers));
            //参数
            System.out.print("\t参数个数："+constructor.getParameterCount());
            Class[] parameterTypes = constructor.getParameterTypes();
            for (Class parameterType : parameterTypes) {
                System.out.println("\t参数类型："+parameterType.getName());
//                System.out.println("\t访问修饰符"+getModifiersMsg(parameterType.getModifiers()));
            }
        }
    }


    @Test
    public void testClassField() throws ClassNotFoundException {
        System.out.println("---------获取类的字段-------");
        Class clz = Class.forName("com.hyl.entity.Student");
        Field[] fields = clz.getDeclaredFields();
        for (Field field : fields) {
            int modifiers = field.getModifiers();
            System.out.print("访问修饰符："+getModifiersMsg(modifiers));
            System.out.print("\t字段类型："+field.getType().getName());
            System.out.println("\t字段名："+field.getName());
        }
    }


    @Test
    public void testClassMethod() throws ClassNotFoundException {
        System.out.println("---------获取类的方法-------");
        Class clz = Class.forName("com.hyl.entity.Student");
        Method[] methods = clz.getDeclaredMethods();
        for (Method method : methods) {
            int modifiers = method.getModifiers();
            System.out.print("访问修饰符："+getModifiersMsg(modifiers));
            System.out.print("\t返回值类型："+method.getReturnType().getName());
            System.out.print("\t方法名："+method.getName());
            Class[] parameterTypes = method.getParameterTypes();
            System.out.print("(");
            for (Class parameterType : parameterTypes) {
                System.out.print(parameterType.getName()+",");
            }
            System.out.println(")");
        }
    }


    @Test
    public void testClass() throws ClassNotFoundException {
        System.out.println("---通过反射操作类的构造器、字段、方法--");
        Class clz = Class.forName("com.hyl.entity.Student");

        try {
           // Student stu = (Student) clz.newInstance(); //这种方式要求，无参构造方法必须存在

            Constructor constructors = clz.getDeclaredConstructor();
            //通过类的构造器，实例化对象
            Object stu2 =  constructors.newInstance(); //这种方式要求，无参构造方法必须存在

            //使用通过类的字段，使用
            Field field = clz.getDeclaredField("stuName");
            //使用=》给字段赋值
            field.setAccessible(true);
            field.set(stu2,"stuName"); //stu2.stuName = "hello"

            //使用通过类的方法，使用
            Method method = clz.getDeclaredMethod("showMsg",String.class);
            //private不能直接调用
            method.setAccessible(true);
            method.invoke(stu2,"hello");

            Method method2 = clz.getDeclaredMethod("setStuName",String.class);
            //private不能直接调用
            method2.setAccessible(true);
            method2.invoke(stu2,"张三");


        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }


    }


    private String getModifiersMsg(int modifiers){
        String tmp = null;
        if(Modifier.isPublic(modifiers)){
            tmp = Modifier.toString(modifiers);
        }else if(Modifier.isPrivate(modifiers)){
            tmp = Modifier.toString(modifiers);
        }else if(Modifier.isProtected(modifiers)){
            tmp = Modifier.toString(modifiers);
        }
        return tmp;
    }
}
